package com.seteam.collabcrossword;

import com.seteam.collabcrossword.exceptions.CollabCrosswordException;

import java.io.Serializable;
import java.util.concurrent.locks.ReentrantLock;

/**
 * This class is an extension of {@link Crossword}. It represents the state of the
 * crossword when it is being solved by two users.
 */
public class CrosswordCurrentState extends Crossword implements Serializable {
    private static final long serialVersionUID = 8125166051659903775L;
    private Tile[][] currentState;
    private final ReentrantLock writeLock = new ReentrantLock();

    /**
     * Constructor
     *
     * @param x the width of the board
     * @param y the height of the board
     * @throws CollabCrosswordException if the width or height is negative
     */
    public CrosswordCurrentState(final int x, final int y) throws CollabCrosswordException {
        super(x, y);
    }

    /**
     * Given an instance of {@link Tile}, this method updates the current state of it
     *
     * @param tile the instance of tile to be used for updating
     */
    public void updateLetter(final Tile tile) {
        final Coordinates coordinates = tile.getCoordinates();
        final int xCoordinate = coordinates.getxCoordinate();
        final int yCoordinate = coordinates.getyCoordinate();
        this.currentState[xCoordinate][yCoordinate] = tile;
    }

    /**
     * Given some coordinates, this method returns the tile present at those
     * coordinates on the board
     *
     * @param coordinates the coordinates of the required tile
     * @return the tile present at those coordinates
     * @throws CollabCrosswordException if the coordinates exceed the size of the board
     */
    public Tile getTile(final Coordinates coordinates)
            throws CollabCrosswordException {
        final int xCoordinate = coordinates.getxCoordinate();
        final int yCoordinate = coordinates.getyCoordinate();
        if (xCoordinate > dimX || yCoordinate > dimY) {
            throw new CollabCrosswordException("Trying to get a tile from out of the board " +
                    "is not possible. Check the coordinates that you are passing to getTile");
        }
        return currentState[xCoordinate][yCoordinate];
    }

    /**
     * Given x and y coordinates, this method returns the tile present at those
     * coordinates on the board
     *
     * @param xCoordinate the x-coordinate of the tile
     * @param yCoordinate the y-coordinate of the tike
     * @return the tile present at those coordinates
     * @throws CollabCrosswordException if the coordinates exceed the size of the board
     */
    public Tile getTile(final int xCoordinate, final int yCoordinate)
            throws CollabCrosswordException {
        if (xCoordinate > dimX || yCoordinate > dimY) {
            throw new CollabCrosswordException("Trying to get a tile from out of the board " +
                    "is not possible. Check the coordinates that you are passing to getTile");
        }
        return currentState[xCoordinate][yCoordinate];
    }

    /**
     * Setter for currentState
     *
     * @param currentState an array of tiles that represents the current state
     */
    public void setCurrentState(final Tile[][] currentState) {
        this.currentState = currentState;
    }

    /**
     * Getter for currentState
     *
     * @return the array of tiles that represents the current state
     */
    public Tile[][] getCurrentState() {
        return currentState;
    }
}
